package com.bsoft.gol.editor.utils;

import ctd.util.JSONUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingClientConnectionManager;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

/**
 * Created by sean on 15/12/3.
 */
public class HttpClientUtils {
    //默认超时 5s
    public final static int connectTimeout = 300000;
    private static final String HTTPS = "https";
    private static HttpClient httpClient;
    private final static Logger logger = LoggerFactory.getLogger(HttpClientUtils.class);
    static {
        PoolingClientConnectionManager cm = new PoolingClientConnectionManager();
        cm.setMaxTotal(50);
        cm.setDefaultMaxPerRoute(50);
        cm.getSchemeRegistry().register(new Scheme(HTTPS, 443, getSSLSocketFactory()));

        DefaultHttpClient defaultHttpClient = new DefaultHttpClient(cm);
        defaultHttpClient.getParams().setIntParameter("http.socket.timeout", 100000);
        httpClient = defaultHttpClient;
    }

    private static SSLSocketFactory getSSLSocketFactory() {
        SSLSocketFactory.getSocketFactory();
        X509TrustManager tm = new X509TrustManager() {
            @Override
            public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {}

            @Override
            public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {}

            @Override
            public X509Certificate[] getAcceptedIssuers() {return null;}
        };
        try {
            SSLContext ctx = SSLContext.getInstance("TLS");
            ctx.init(null, new TrustManager[]{tm}, null);
            SSLSocketFactory socketFactory = new SSLSocketFactory(ctx, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
            return socketFactory;
        }
        catch (Exception e){
            throw new IllegalStateException(e);
        }
    }

    public static <T> T doGet(String url,Class<T> t) throws IOException{
        HttpGet get = new HttpGet(url);
        try {
            HttpResponse response = httpClient.execute(get);
            T res;
            int statusCode = response.getStatusLine().getStatusCode();
            if(statusCode < 300){
                HttpEntity entity = response.getEntity();
                res = JSONUtils.parse(entity.getContent(),t);
                EntityUtils.consume(entity);
            }
            else{
                throw new IOException("http get[" + url + "] failed,statuCode [" + statusCode + "].");
            }
            return res;
        }
        catch (Exception e){
            if(!get.isAborted()) {
                get.abort();
            }
            throw new IOException(e);
        }
    }

    public static HttpStreamResponse doGetAsInputStream(String url) throws IOException {
        HttpGet get = new HttpGet(url);
        try {
            HttpResponse response = httpClient.execute(get);
            String res;
            int statusCode = response.getStatusLine().getStatusCode();
            if(statusCode < 300){
                HttpEntity entity = response.getEntity();
                return new HttpStreamResponse(entity.getContentType().getValue(),entity.getContentLength(),entity.getContent());
            }
            else{
                throw new IOException("http get[" + url + "] failed,statuCode [" + statusCode + "].");
            }
        }
        catch (Exception e){
            if(!get.isAborted()) {
                get.abort();
            }
            throw new IOException(e);
        }
    }

    public static String doGet(String url) throws IOException {
        HttpGet get = new HttpGet(url);
        try {
            HttpResponse response = httpClient.execute(get);
            String res;
            int statusCode = response.getStatusLine().getStatusCode();
            if(statusCode < 300){
                HttpEntity entity = response.getEntity();
                res = EntityUtils.toString(entity);
                EntityUtils.consume(entity);
            }
            else{
                throw new IOException("http get[" + url + "] failed,statuCode [" + statusCode + "].");
            }
            return res;
        }
        catch (Exception e){
            if(!get.isAborted()) {
                get.abort();
            }
            throw new IOException(e);
        }
    }

    public static String doPostJson(String url,Object body) throws IOException {
        HttpPost post = new HttpPost(url);
        try {
            String res;
            if(body != null) {
                post.setEntity(new StringEntity(JSONUtils.toString(body), ContentType.APPLICATION_JSON));
            }
            HttpResponse response = httpClient.execute(post);
            int statusCode = response.getStatusLine().getStatusCode();
            if(statusCode < 300){
                HttpEntity entity = response.getEntity();
                res = EntityUtils.toString(entity);
                EntityUtils.consume(entity);
            }
            else{
                throw new IOException("http get[" + url + "] failed,statuCode [" + statusCode + "].");
            }
            return res;
        }
        catch (Exception e){
            if(!post.isAborted()) {
                post.abort();
            }
            throw new IOException(e);
        }
    }

    public static String doPost(String url, String json) throws IOException{
        logger.info("url :" + url + " , param :" + json);
        HttpPost post = new HttpPost(url);
        post.addHeader("Content-Type", "application/json;charset=utf-8");
        StringEntity s;
        try {
            s = new StringEntity(json, "UTF-8");

            post.setEntity(s);

            RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(connectTimeout).setConnectTimeout(connectTimeout).setConnectionRequestTimeout(connectTimeout).build();
            post.setConfig(requestConfig);

            long start = System.currentTimeMillis();
            HttpResponse response = httpClient.execute(post);
            long end = System.currentTimeMillis();
            HttpEntity entity = response.getEntity();
            try {
                if (entity != null) {
                    String str = EntityUtils.toString(entity, "UTF-8");
                    logger.info("返回值str :" + str );

                    return str;
                }
            } finally {
                if (entity != null) {
                    entity.getContent().close();
                }
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            post.releaseConnection();
        }
        return "";
    }

    /**
     * 使用apache的HttpClient发送http
     *
     * @param wsdlURL
     *            请求URL
     * @param contentType
     *            如:application/json;charset=utf8
     * @param content
     *            数据内容
     * @DATE 2018年9月22日 下午10:29:17
     */
    public static String doHttpPostByHttpClient(String wsdlURL, String contentType, String content)
            throws ClientProtocolException, IOException {
        // 获得Http客户端(可以理解为:你得先有一个浏览器;注意:实际上HttpClient与浏览器是不一样的)
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();
        // 创建Post请求
        HttpPost httpPost = new HttpPost(wsdlURL);
        StringEntity entity = new StringEntity(content.toString(), "UTF-8");
        // 将数据放入entity中
        httpPost.setEntity(entity);
        httpPost.setHeader("Content-Type", contentType);
        // 响应模型
        CloseableHttpResponse response = null;
        String result = null;
        try {
            // 由客户端执行(发送)Post请求
            response = httpClient.execute(httpPost);
            // 从响应模型中获取响应实体
            // 注意:和doHttpPostByRestTemplate方法用的不是同一个HttpEntity
            org.apache.http.HttpEntity responseEntity = response.getEntity();
            System.out.println("响应ContentType为:" + responseEntity.getContentType());
            System.out.println("响应状态为:" + response.getStatusLine());
            if (responseEntity != null) {
                result = EntityUtils.toString(responseEntity);
                System.out.println("响应内容为:" + result);
            }
        } finally {
            // 释放资源
            if (httpClient != null) {
                httpClient.close();
            }
            if (response != null) {
                response.close();
            }
        }
        return result;
    }

}
